package com.solution.admin.point.service.impl;

import java.math.BigDecimal;
import java.util.Date;
import java.util.List;
import java.util.Map;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import com.solution.admin.point.constants.PointConstants.PointOperateFlag;
import com.solution.admin.point.constants.PointConstants.PointOperateType;
import com.solution.admin.point.dao.PointDao;
import com.solution.admin.point.dao.PointLogDao;
import com.solution.admin.point.entity.PointEntity;
import com.solution.admin.point.entity.PointLogEntity;
import com.solution.admin.point.service.PointService;
import com.solution.common.dao.BaseDao;
import com.solution.common.page.PageBean;
import com.solution.common.page.PageParam;
import com.solution.common.service.impl.BaseServiceImpl;
import com.solution.common.utils.string.StringUtil;

/**
 * 积分信息service实现层
 * 
 * @author xu_cc
 * @date 2017-10-20 14:19:17
 */
@Service
public class PointServiceImpl extends BaseServiceImpl<PointEntity> implements PointService {

	private Logger logger = LoggerFactory.getLogger(PointServiceImpl.class);
	/**
	 * 积分信息接口
	 */
	@Autowired
	private PointDao pointDao;

	@Autowired
	PointLogDao pointLogDao;

	protected BaseDao<PointEntity> getDao() {
		return this.pointDao;
	}

	/**
	 * 根据客户ID获取积分信息
	 * 
	 * @Title: getPointByCustomerId
	 * @Description:(描述)
	 * @param customerId
	 * @return PointEntity
	 * @author xu_cc
	 * @throws Exception
	 *             exception
	 * @Date 创建时间：2017年10月23日 上午10:50:45
	 */
	public PointEntity getPointByCustomerId(Long customerId) {
		return pointDao.getPointByCustomerId(customerId);
	}

	/**
	 * 积分操作通用方法<br>
	 * largerThenSetZero:true/false<br>
	 * (扣减时，如果操作积分大于当前积分，则将当前积分置为0，<br>
	 * 如果true，标识同意置为0，<br>
	 * 如果是false，则扣减积分操作终止并抛出异常)
	 * 
	 * @param customerId
	 *            客户ID
	 * @param optFlag
	 *            操作标识（1=加，0=减）
	 * @param optType
	 *            操作类型
	 * @param optPoint
	 *            操作积分
	 * @param adjustReason
	 *            操作原因
	 * @param billCode
	 *            单据编码
	 * @param billTime
	 *            单据时间
	 * @param optUser
	 *            操作人
	 * @param largerThenSetZero
	 *            标识
	 * @return int
	 * @author xu_cc
	 * @throws Exception
	 *             exception
	 * @Date 创建时间：2017年10月23日 上午10:43:49
	 */
	@Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
	public int doOperatePointCommon(Long customerId, Integer optFlag, String optType, BigDecimal optPoint, String adjustReason, String billCode,
	        Date billTime, String optUser, boolean largerThenSetZero) throws Exception {
		// 结果是:-1 小于,0 等于,1 大于
		if (optPoint.compareTo(BigDecimal.ZERO) == -1) {
			// 如果操作积分小于0，报错
			throw new Exception(StringUtil.formatString("操作积分不能小于0，客户编号：%s，操作类型：%s，操作积分：%s ！", customerId,
			        PointOperateType.getNameById(Integer.parseInt(optType)), optPoint));
		} else if(optPoint.compareTo(BigDecimal.ZERO) == 0) {
			// 如果最终操作的积分是0（比如未设置积分签到规则，即使签到，送的积分也是0，就没这个必要了）
			// 结果是:-1 小于,0 等于,1 大于
			// 直接算成功吧
			return 1;
		} else {
			// 获取当前客户积分
			PointEntity point = pointDao.getPointByCustomerId(customerId);
			// 操作前积分
			BigDecimal beforePoint = point.getPoint();
			BigDecimal afterPoint = null;
			// 操作后积分
			if (optFlag.equals(PointOperateFlag.FLAG_ADD.getId())) {
				// 操作标识-加
				afterPoint = point.getPoint().add(optPoint);
			} else if (optFlag.equals(PointOperateFlag.FLAG_MINUS.getId())) {
				// 操作标识-减
				// 判断积分够不够减
				// 结果是:-1 小于,0 等于,1 大于
				if (point.getPoint().compareTo(optPoint) == -1) {
					// 如果当前积分小于操作积分
					if (largerThenSetZero) {
						// 允许操作积分大于当前积分时，将当前积分置为0
						String error = StringUtil.formatString("操作积分不能小于0，客户编号：%s ，操作类型：%s ，操作积分：%s ，当前积分：%s ，积分不足，因此操作积分设为当前积分。", customerId,
								PointOperateType.getNameById(Integer.parseInt(optType)), optPoint, point.getPoint());
						logger.error(error);
						// 操作积分是当前积分
						optPoint = point.getPoint();
						// 最终当前积分是 0
						afterPoint = BigDecimal.ZERO;
					} else {
						// 当前积分小于操作积分，终止操作并报错
						throw new Exception("积分不足！当前积分：" + point.getPoint() + " 需要扣减积分：" + optPoint);
					}
				} else {
					// 当前积分大于或等与操作积分
					afterPoint = point.getPoint().subtract(optPoint);
				}
			} else {
				throw new Exception("未知的操作！");
			}
			// 操作积分信息表
			// 最新积分
			point.setPoint(afterPoint);
			// 操作人
			point.setModifier(optUser);
			// 执行更新
			pointDao.updatePoint(point);
			// 插入日志
			PointLogEntity pointLog = new PointLogEntity(customerId, optType, optFlag, beforePoint, optPoint, afterPoint, adjustReason, billCode,
					billTime, optUser);
			pointLogDao.savePointLog(pointLog);
			return 1;
		}
	}

	/**
	 * 保存积分信息
	 * 
	 * @param pointEntity
	 *            积分信息实体
	 * @return Long 添加成功积分信息的ID
	 * @author xu_cc
	 * @date 2017-10-20 14:19:17
	 */
	public long savePoint(PointEntity pointEntity) {
		return pointDao.savePoint(pointEntity);
	}

	/**
	 * 分页查询积分信息
	 * 
	 * @param pageParam
	 *            分页参数
	 * @param paramMap
	 *            查询参数
	 * @return PageBean 分页参数和分页数据
	 * @author xu_cc
	 * @date 2017-10-20 14:19:17
	 */
	@Override
	public PageBean listPointPage(PageParam pageParam, Map<String, Object> paramMap) {
		return pointDao.listPointPage(pageParam, paramMap);
	}

	/**
	 * 根据ID查询用户信息
	 * 
	 * @param id
	 *            用户id
	 * @return pointEntity 用户对象
	 * @author xu_cc
	 * @date 2017-10-20 14:19:17
	 */
	public PointEntity getPointById(Long id) {
		return pointDao.getById(id.longValue());
	}

	/**
	 * 更新用户
	 * 
	 * @param pointEntity
	 *            用户实体
	 * @return Long 更新是否成功，>1代表更新成功
	 * @author xu_cc
	 * @date 2017-10-20 14:19:17
	 */
	@Override
	public int updatePoint(PointEntity pointEntity) {
		return pointDao.updatePoint(pointEntity);
	}

	/**
	 * 根据条件查询积分信息
	 * 
	 * @param param
	 * @return 数据列表
	 * @author xu_cc
	 * @date 2017-10-20 14:19:17
	 */
	@Override
	public List<PointEntity> listPoint(Map<String, Object> param) {
		return pointDao.listPoint(param);
	}

	/**
	 * 删除积分信息
	 * 
	 * @param
	 * @return int 返回删除记录条数
	 * @author xu_cc
	 * @date 2017-10-20 14:19:17
	 */
	public int deletePointById(long id) {
		return pointDao.deleteById(id);
	}

}
